package switchviz.graphic.gauge.graph2d.scale;

import javax.media.opengl.GL;
import javax.swing.JPanel;

import org.jdom.Element;

import switchviz.graphic.GraphicUtils;
import switchviz.graphic.gauge.graph2d.Graph2dDataModel.ScaleMode;

public class Graph2dBoard 
{
	private Graph2dBoardDataModel _dm;
	private Element _root = null;
	private Graph2dBoardPanel _boardpanel = null;
	private Graph2dBoardPersistence _nodehandler = null;

	private ScaleMode _scalemode;
	private int _min;
	private int _max;
	private boolean _enable;
	private boolean buildList = true;
	
	public Graph2dBoard(Element root, ScaleMode scalemode, int min, int max, boolean enable)
	{
		_scalemode = scalemode;
		_min = min;
		_max = max;
		_enable = enable;
		
		_root = root;
		
		getBoardModel();
	}

	public void initialize(GL gl)
	{
		buildLists(gl);
	}
	
	private void buildLists(GL gl)
	{
		_dm.setList(gl.glGenLists(1));
		gl.glNewList(_dm.getList(), GL.GL_COMPILE);
		
		
		gl.glPushMatrix();
		
		if (_enable)
			gl.glColor4f(_dm.getScalecolor()[0], _dm.getScalecolor()[1], _dm.getScalecolor()[2], 1.0f);
		else
			gl.glColor4f(_dm.getScalecolor()[0], _dm.getScalecolor()[1], _dm.getScalecolor()[2], 0.3f);
			
		gl.glTranslatef(-1.0f, -1.0f, 0.0f);
		gl.glScalef(2.0f, 2.0f, 1.0f);
		
		
		gl.glBegin(GL.GL_QUADS);
		
		
		
		float steps = 1.0f/_dm.getNumbigticks();
		
		for (int i=0; i<=_dm.getNumbigticks(); i++)
		{
			float offset = (i*steps);
			
			gl.glVertex2f(0.0f, offset+(_dm.getWidthbigticks()/2));
			gl.glVertex2f(0.0f, offset-(_dm.getWidthbigticks()/2));
			gl.glVertex2f(_dm.getLengthbigticks(), offset-(_dm.getWidthbigticks()/2));
			gl.glVertex2f(_dm.getLengthbigticks(), offset+(_dm.getWidthbigticks()/2));
			
			gl.glVertex2f(1.0f, offset+(_dm.getWidthbigticks()/2));
			gl.glVertex2f(1.0f, offset-(_dm.getWidthbigticks()/2));
			gl.glVertex2f(1.0f-_dm.getLengthbigticks(), offset-(_dm.getWidthbigticks()/2));
			gl.glVertex2f(1.0f-_dm.getLengthbigticks(), offset+(_dm.getWidthbigticks()/2));
		
			if (i != _dm.getNumbigticks())
				switch (_scalemode)
				{
				case LINEAR:
					
					float steps2 = (((i+1)*steps-offset))/_dm.getNumsmallticks();
					
					for (int j=1; j<_dm.getNumsmallticks(); j++)
					{
						gl.glVertex2f(0.0f, offset + (j*steps2)+(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(0.0f, offset + (j*steps2)-(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(_dm.getLengthsmallticks(), offset + (j*steps2)-(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(_dm.getLengthsmallticks(), offset + (j*steps2)+(_dm.getWidthsmallticks()/2));
						
						gl.glVertex2f(1.0f, offset + (j*steps2)+(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(1.0f, offset + (j*steps2)-(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(1.0f-_dm.getLengthsmallticks(), offset + (j*steps2)-(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(1.0f-_dm.getLengthsmallticks(), offset + (j*steps2)+(_dm.getWidthsmallticks()/2));
					}
					break;
					
				case LOGARITHM:
					
					float steps3 = (((i+1)*steps)-offset)/(float)Math.log10(_dm.getNumsmallticks());
					
					for (int j=1; j<_dm.getNumsmallticks(); j++)
					{
						float offset2 = offset + (float) (Math.log10(j)*steps3);
						
						gl.glVertex2f(0.0f, offset2+(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(0.0f, offset2-(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(_dm.getLengthsmallticks(), offset2-(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(_dm.getLengthsmallticks(), offset2+(_dm.getWidthsmallticks()/2));
						
						gl.glVertex2f(1.0f, offset2+(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(1.0f, offset2-(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(1.0f-_dm.getLengthsmallticks(), offset2-(_dm.getWidthsmallticks()/2));
						gl.glVertex2f(1.0f-_dm.getLengthsmallticks(), offset2+(_dm.getWidthsmallticks()/2));
					}
					break;
				}
		}
		
		gl.glEnd();
		
		gl.glPointSize(1.0f);
		gl.glBegin(GL.GL_POINTS);
		
		for (int i=0; i<=_dm.getNumbigticks(); i++)
		{
			gl.glVertex2f(0.1f, (i*steps));
			gl.glVertex2f(0.2f, (i*steps));
			gl.glVertex2f(0.3f, (i*steps));
			gl.glVertex2f(0.4f, (i*steps));
			gl.glVertex2f(0.5f, (i*steps));
			gl.glVertex2f(0.6f, (i*steps));
			gl.glVertex2f(0.7f, (i*steps));
			gl.glVertex2f(0.8f, (i*steps));
			gl.glVertex2f(0.9f, (i*steps));
		}
		
		gl.glEnd();
		
		gl.glColor4f(_dm.getLabelcolor()[0], _dm.getLabelcolor()[1], _dm.getLabelcolor()[2], 1.0f);
		
		int label = _min;
		int labelstep = (_max-_min) / _dm.getNumbigticks();
		
		switch (_scalemode)
		{
		case LINEAR:
			label = _min;
			labelstep = (_max-_min) / _dm.getNumbigticks();
			break;
		case LOGARITHM:
			label = (int) Math.max(_min, 1);
			labelstep = 10;
			break;
		}
		
		gl.glTranslatef(1.04f, 0.0f, 0.0f);
		
		for (int i=0; i<=_dm.getNumbigticks(); i++)
		{
			GraphicUtils.drawString(gl, 5, GraphicUtils.ALIGN_LEFT, 0, "" + label);
			gl.glTranslatef(0.0f, steps, 0.0f);
			
			switch (_scalemode)
			{
			case LINEAR:
				label += labelstep;
				break;
			case LOGARITHM:
				label *= labelstep;
				break;
			}
		}
		gl.glPopMatrix();
		
		gl.glEndList();
		
		buildList = false;
	}
	
	
	public void draw(GL gl)
	{
		if (buildList)
			buildLists(gl);
		
		gl.glCallList(_dm.getList());
	}

	public JPanel getSetupPanel() 
	{
		return getBoardPanel();
	}

	private Graph2dBoardPanel getBoardPanel() 
	{
		if (_boardpanel == null)
			_boardpanel = new Graph2dBoardPanel(_root);
		return _boardpanel;
	}

	public Element getElement() 
	{
		return getBoardPanel().getElement();
	}

	public Graph2dBoardDataModel getBoardModel() 
	{
		if (_dm == null)
			_dm = getNodeHandler().getDataModelFromElement();
		return _dm;
	}
	
	private Graph2dBoardPersistence getNodeHandler()
	{
		if(_nodehandler == null)
			_nodehandler = new Graph2dBoardPersistence(_root);
		return _nodehandler;
	}
}
